package io.zrpc.core.common.log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.MessageFormat;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class LogCodes {
    private final static Logger LOGGER = LoggerFactory.getLogger(LogCodes.class);
    public static final String CODE_DOES_NOT_EXIST = "LogCodes.getLog error, code does not exist:";
    public static final String LITE_LOG_FORMAT_ERROR = "LogCode.getLiteLog format error,codeOrMsg=";
    public static final String LOG_FORMAT_ERROR = "LogCode.getLog format error,code=";

    protected static final Map<String, String> LOG_CODES = new ConcurrentHashMap<>();
    protected final static String LOG = "RPC-%s: %s %s";
    protected final static String NOTE = "";
    // 00 通用
    // 00001 Config
    public static final String ERROR_NOT_FOUND_KEY = "000010001";
    public static final String ERROR_LOAD_RPC_CONFIGS = "000010002";


    // 01 启动
    // 01000 provider
    // 01001 consumer
    // 01003 listener
    // 01004 module
    // 01005 registry
    // 01006 event
    // 01007 ext
    public static final String ERROR_EXTENSION_NOT_FOUND = "010070001";


    // 02 运行
    // 02000 transport
    // 02001 provider
    // 02002 provider
    // 02003 泛化
    // 02004 loadbalancer
    // 02005 router
    // 02006 invoke
    // 02007 connectionholder
    // 02008 codec
    // 02009 context
    // 02010 tracer
    // 02011 protocol
    // 02012 filter
    // 02013 event
    // 02999 未知错误


    /**
     * 该方法不应该由日志输出类直接使用，RPC 的所有的日志输出均应该使用 {@link Logger} 类
     * <p>
     * 仅当需要设置 Exception 的提示消息的时候才可使用该方法
     *
     * @param code 日志码
     * @return 日志内容
     */
    public static String getLog(String code) {
        if (!LOG_CODES.containsKey(code)) {
            LOGGER.error(CODE_DOES_NOT_EXIST + code);
            return CODE_DOES_NOT_EXIST + code;
        }
        try {
            return String.format(LOG, code, LOG_CODES.get(code), LogCodes.NOTE);
        } catch (Throwable e) {
            LOGGER.error(LOG_FORMAT_ERROR + code, e);
        }
        return LOG_FORMAT_ERROR + code;
    }

    /**
     * 当输入为日志码的时候，输出日志码对应的日志内容
     * 否则直接输出日志内容
     *
     * @param codeOrMsg 日志码或日志输出
     * @return 基本日志输出，不包含日志码
     */
    public static String getLiteLog(String codeOrMsg) {
        if (!LOG_CODES.containsKey(codeOrMsg)) {
            return codeOrMsg;
        }
        try {
            return LOG_CODES.get(codeOrMsg);
        } catch (Throwable e) {
            LOGGER.error(LITE_LOG_FORMAT_ERROR + codeOrMsg, e);
        }
        return LITE_LOG_FORMAT_ERROR + codeOrMsg;
    }

    public static String getLog(String code, Object... messages) {
        String message = LOG_CODES.get(code);
        if (message == null) {
            LOGGER.error(CODE_DOES_NOT_EXIST + code);
            return CODE_DOES_NOT_EXIST + code;
        }
        try {
            return String.format(LOG, code, MessageFormat.format(message, messages), LogCodes.NOTE);
        } catch (Throwable e) {
            LOGGER.error(LOG_FORMAT_ERROR + code, e);
        }
        return LOG_FORMAT_ERROR + code;
    }

    /**
     * 当输入为日志码的时候，输出日志码对应的日志内容
     * 否则直接输出日志内容
     *
     * @param codeOrMsg 日志码或日志输出
     * @return 基本日志输出，不包含日志码
     */
    public static String getLiteLog(String codeOrMsg, Object... messages) {
        String message = LOG_CODES.get(codeOrMsg);

        if (message == null) {
            message = codeOrMsg;
        }

        try {
            return MessageFormat.format(message, messages);
        } catch (Throwable e) {
            LOGGER.error(LITE_LOG_FORMAT_ERROR + codeOrMsg, e);
        }
        return LITE_LOG_FORMAT_ERROR + codeOrMsg;
    }
}
